//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <core.h>
#include <mantle.h>

ELAPI DzIoRemap(
    Address virtualAddr,
    MemorySize size,
    Address physicalAddr,
    MemoryMapFlags flags,
    Int32 protect,
    Address *pVirtualAddr)
{
    assert(0 != protect);
    assert(::GetCurrentProcess());

    if (NULL == pVirtualAddr || PAGE_OFFSET(virtualAddr)
        || PAGE_OFFSET(physicalAddr) || 0 >= size || PAGE_OFFSET(size)) {
        return E_INVALID_ARGUMENT;
    }

    if (flags & MemoryMap_Fixed) {
        if (virtualAddr < VIRTUAL_ALLOC_BASE
            || virtualAddr >= VIRTUAL_ALLOC_LIMIT) {
            return E_INVALID_ARGUMENT;
        }
    }

    // we only permit user alloc a private space
    flags = (flags | MemoryMap_Private) & (~MemoryMap_Shared);

    // IoRemap must has MemoryProtection_IO property
    protect = (MemoryProtection)(protect | IoRemapFlag_Direct);

    return ::GetCurrentProcess()->m_AS.Remap( \
        virtualAddr, size, physicalAddr, flags, protect,
        (UInt32*)pVirtualAddr);
}

ELAPI DzMemoryUnmap(
    Address virtualAddr,
    UInt32 uSize)
{
    assert(::GetCurrentProcess());

    if (PAGE_OFFSET(virtualAddr) || PAGE_OFFSET(uSize)) {
        return E_INVALID_ARGUMENT;
    }

    return ::GetCurrentProcess()->m_AS.Unmap(virtualAddr, uSize);
}

ELAPI DzIoUnmap(
    Address virtualAddr,
    UInt32 uSize)
{
    return DzMemoryUnmap(virtualAddr, uSize);
}

ELAPI DzMemoryQueryPhysicalBlock(
    Address virtualAddr,
    Address *pPhysicalAddr,
    MemorySize *pSize)
{
    assert(::GetCurrentProcess());

    if (!FALL_INTO(virtualAddr, VIRTUAL_ALLOC_BASE, VIRTUAL_ALLOC_SIZE)) {
        return E_INVALID_ARGUMENT;
    }

    if (NULL == pPhysicalAddr && NULL == pSize) return E_INVALID_ARGUMENT;

    return ::GetCurrentProcess()->m_AS.QueryPhysicalBlock(
                virtualAddr, pPhysicalAddr, pSize);
}
